﻿
//词法分析类
//CutSource() 函数处理原始输入程序
//识别基本单词和符号,获取每个词的位置信息
//如行数, 列数等,用于错误跟踪

namespace n_PyAccidence
{
using System;
using System.Text;
using n_PyCharType;
using n_PyCOper;
using n_PyKeyWord;
using n_PyWordList;
using n_PyWordNode;

public static class Accidence
{
	static int i;
	public static string Source;
	const int FileMaxNumber = 300;
	const int MaxDefineNumber = 1000;
	
	const int TabToSpaceNumber = 4;
	
	//初始化
	public static void Init()
	{
		
	}
	
	//词法分析,获取每个词的位置信息
	public static void CutSource( string src )
	{
		Source = pythontoc( src );
		i = 0;
		
		//清空词法列表
		WordList.Reset();
		
		//递归分析词法,生成词法列表
		AddWord( 0 );
		WordNode n = new WordNode( "*结束", 0, 0, 0, 0, 0, 0 );
		WordList.Add( n );
		
		//宏替换处理
		//Define();
	}
	
	//词法分析,获取每个词的位置信息（仅用于着色）
	public static void DrawCutSource( string src )
	{
		//Source = pythontoc( src );
		Source = src;
		
		i = 0;
		
		//清空词法列表
		WordList.Reset();
		
		//递归分析词法,生成词法列表
		AddWord( 0 );
		WordNode n = new WordNode( "*结束", 0, 0, 0, 0, 0, 0 );
		WordList.Add( n );
		
		//宏替换处理
		//Define();
	}
	
	//python转C语言预处理
	static string pythontoc( string src )
	{
		//src = src.Replace( "\t", "    " );
		
		string[] s = src.Split( '\n' );
		
		int TabNumber = 0;
		string Result = null;
		int NextTabNumber = 0;
		for( int i = 0; i < s.Length; ++i ) {
			//移除注释
			int n0 = s[i].IndexOf( "#" );
			if( n0 != -1 ) {
				s[i] = s[i].Remove( n0 );
			}
			//如果是空行则忽略
			if( s[i].Trim( " \t".ToCharArray() ) == "" ) {
				s[i] = "";
			}
		}
		for( int i = 0; i < s.Length; ++i ) {
			
			//缩进规则计算
			if( i < s.Length - 1 ) {
				if( s[i + 1] == "" ) {
					//NextTabNumber = 0;
				}
				else {
					NextTabNumber = 0;
					for( int n = 0; n < s[i+1].Length; ++n ) {
						if( s[i+1][n] == ' ' ) {
							NextTabNumber++;
							continue;
						}
						if( s[i+1][n] == '\t' ) {
							NextTabNumber += TabToSpaceNumber;
							continue;
						}
						break;
					}
					if( NextTabNumber % TabToSpaceNumber != 0 ) {
						s[i] = "(ERROR:tab)" + NextTabNumber + " " + s[i];
					}
					NextTabNumber /= TabToSpaceNumber;
				}
			}
			else {
				NextTabNumber = 0;
			}
			
			string tt = s[i].TrimStart( " \t".ToCharArray() );
			
			if( (
				tt.StartsWith( "def " ) ||
				tt.StartsWith( "class " ) ||
				
				tt.StartsWith( "if " ) ||
				tt.StartsWith( "for " ) ||
				tt.StartsWith( "while " ) ||
				
				tt.StartsWith( "if(" ) ||
				tt.StartsWith( "for(" ) ||
				tt.StartsWith( "while(" ) 
			) && TabNumber == NextTabNumber ) {
				//...
			}
			else if( TabNumber + 1 == NextTabNumber ) {
				if( i > 0 ) {
					s[i] += "{";
				}
			}
			else {
				if( tt == ((char)3).ToString() || tt == ((char)2).ToString() || tt.StartsWith( ((char)1).ToString() ) && tt.Length == 2 ) {
					//...
				}
				else if( tt != "" ) {
					
					s[i] += ";";
					
				}
				if( TabNumber > NextTabNumber ) {
					int num = TabNumber - NextTabNumber;
					for( int n = 0; n < num; ++n ) {
						s[i] += "}";
					}
				}
			}
			TabNumber = NextTabNumber;
			
			Result += s[i] + "\n";
		}
		return "class root():{\n" + Result + "}";
	}
	
	//分析词法
	static void AddWord( int CurrentFileIndex )
	{
		int FirstIndex = i;
		int Line = 0;
		int WordIndex = 0;
		StringBuilder Result = new StringBuilder( "" );
		
		while( i < Source.Length ) {
			
			//读取字符常量
			char c = Source[ i ];
			
			//判断是否分界符
			if( c == '{' || c == '}' || c == ';' || c == ',' || c == ':' || c == '(' || c == ')' ||
			    c == '.' || c == '?' ) {
				WordIndex = i;
				int RowIndex0 = i - FirstIndex;
				WordNode n = new WordNode(
					c.ToString(), CurrentFileIndex, Line, RowIndex0, WordIndex, WordNode.SPLIT, 1 );
				WordList.Add( n );
				++i;
				continue;
			}
			//判断是否字符
			if( c == '\'' ) {
				WordIndex = i;
				int Index = i - FirstIndex;
				Result.Length = 0;
				do {
					Result.Append( Source[ i ] );
					++i;
					if( i >= Source.Length ) {
						--i;
						break;
					}
					if( Source[ i ] == '\n' ) {
						--i;
						break;
					}
					if( Source[ i ] == '\'' ) {
						if( Source[ i - 1 ] != '\\' ) {
							Result.Append( Source[ i ] );
							break;
						}
					}
				}
				while( true );
				++i;
				WordNode n = new WordNode(
					Result.ToString(), CurrentFileIndex, Line, Index, WordIndex, WordNode.CHAR, i - WordIndex );
				WordList.Add( n );
				continue;
			}
			//判断是否注释
			if( c == '#' ) {
				while( i < Source.Length && Source[ i ] != '\n' ) {
					++i;
				}
				continue;
			}
			//判断是否字符串
			if( c == '"' ) {
				WordIndex = i;
				int Index = i - FirstIndex;
				Result.Length = 0;
				do {
					Result.Append( Source[ i ] );
					++i;
					if( i == Source.Length ) {
						--i;
						break;
					}
					if( Source[ i ] == '\n' ) {
						--i;
						break;
					}
					if( Source[ i ] == '"' ) {
						if( Source[ i - 1 ] != '\\' ) {
							Result.Append( Source[ i ] );
							//截取字符串扩展信息(如果存在的话)
							if( i + 1 < Source.Length && Source[ i + 1 ] == '(' && Source[ i + 1 ] != '\n' ) {
								while( i + 1 < Source.Length ) {
									i += 1;
									Result.Append( Source[ i ] );
									if( Source[ i ] == ')' ) {
										break;
									}
								}
							}
							break;
						}
						if( Source[ i - 2 ] == '\\' ) {
							break;
						}
					}
					
				}
				while( true );
				++i;
				WordNode n = new WordNode(
					Result.ToString(), CurrentFileIndex, Line, Index, WordIndex, WordNode.STRING, i - WordIndex );
				WordList.Add( n );
				continue;
			}
			//判断是否空白符
			if( c == '\n' ) {
				++Line;
				++i;
				FirstIndex = i;
				continue;
			}
			//判断是否空白符
			if( c == ' ' || c == '\t' || c == (char)13 ) {
				++i;
				continue;
			}
			//判断是否为行号初始字符
			if( c == 3 ) {
				Line = 0;
				++i;
				continue;
			}
			//判断文件包含标记
			if( c == 1 ) {
				++i;
				int FileIndex = (int)Source[ i ];
				++i;
				AddWord( FileIndex );
				continue;
			}
			//判断文件包含标记
			if( c == 2 ) {
				++i;
				return;
			}
			/*
			//判断是否注释
			if( c == '#' ) {
				while( i < Source.Length && Source[ i ] != '\n' ) {
					++i;
				}
				++i;
				continue;
			}
			*/
			//判断是否宏替换
			if( c == '@' ) {
				Result.Length = 0;
				int Index = i - FirstIndex;
				while( i < Source.Length && Source[ i ] != '\n' ) {
					Result.Append( Source[ i ] );
					++i;
				}
				WordNode n = new WordNode(
					Result.ToString(), CurrentFileIndex, Line, Index, WordIndex, WordNode.FRONT, i - WordIndex );
				n.ColorIndex = 0;
				WordList.Add( n );
				continue;
			}
			//判断是否标识符
			if( CharType.isLetterOrNumber( c ) ) {
				bool NumberStart = CharType.isNumber( c );
				WordIndex = i;
				Result.Length = 0;
				int Index = i - FirstIndex;
				do {
					Result.Append( Source[ i ] );
					++i;
				}
				while( i < Source.Length && (CharType.isLetterOrNumber( Source[ i ] ) || (NumberStart && Source[i] == '.' ) ) );
				string Ident = Result.ToString();
				
				int TypeIndex = 0;
				int ColorIndex = 0;
				if( KeyWord.isKeyWord( Ident, ref ColorIndex )  ) {
					TypeIndex = WordNode.KEYWORD;
				}
				else if( Ident[ 0 ] == '#' ) {
					TypeIndex = WordNode.SYS;
					
				}
				else if( Ident[ 0 ] >= '0' && Ident[ 0 ] <= '9' ) {
					TypeIndex = WordNode.NUMBER;
				}
				else {
					TypeIndex = WordNode.IDENT;
				}
				WordNode n = new WordNode(
					Ident, CurrentFileIndex, Line, Index, WordIndex, TypeIndex, i - WordIndex );
				n.ColorIndex = ColorIndex;
				WordList.Add( n );
				continue;
			}
			//添加运算符号
			WordIndex = i;
			int RowIndex = i - FirstIndex;
			int j = i + 2;
			if( j >= Source.Length ) {
				j = Source.Length - 1;
			}
			//获取初始运算符
			StringBuilder Oper = new StringBuilder( Source.Substring( i, j - i + 1 ) );
			while( j != i ) {
				//递减测试运算符
				if( COper.isExist( Oper.ToString() ) ) {
					break;
				}
				Oper.Remove( Oper.Length - 1, 1 );
				--j;
			}
			i = j + 1;
			WordNode nn = new WordNode(
				Oper.ToString(), CurrentFileIndex, Line, RowIndex, WordIndex, WordNode.OPER, i - WordIndex );
			WordList.Add( nn );
		}
	}
	
	//宏替换处理
	static void Define()
	{
		//建立宏定义列表
		int[] DefineNumberList = new int[ FileMaxNumber ];
		string[][][] DefineList = new string[ FileMaxNumber ][][];
		for( int i = 0; i < DefineList.Length; ++i ) {
			DefineList[ i ] = new string[ MaxDefineNumber ][];
		}
		//获取源词法列表
		WordNode[] SourceWord = WordList.GetList();
		int Length = WordList.GetLength();
		WordNode[] TargetWord = new WordNode[ SourceWord.Length ];
		
		//记录宏替换定义
		int newLength = 0;
		for( int i = 0; i < Length; ++i ) {
			//记录宏定义
			if( SourceWord[ i ].TypeIndex != WordNode.FRONT ) {
				continue;
			}
			int FileIndex = SourceWord[ i ].FileIndex;
			int DefineNumber = DefineNumberList[ FileIndex ];
			
			string[] Cut = SourceWord[ i ].Word.Split( ' ' );
			if( Cut[ 0 ] != "@define" || Cut.Length != 3 ) {
				SourceWord[ i ].TypeIndex = WordNode.IDENT;
				continue;
			}
			DefineList[ FileIndex ][ DefineNumber ] = new string[ 2 ];
			DefineList[ FileIndex ][ DefineNumber ][ 0 ] = Cut[ 1 ];
			DefineList[ FileIndex ][ DefineNumber ][ 1 ] = Cut[ 2 ];
			++DefineNumberList[ FileIndex ];
		}
		//替换宏定义
		for( int i = 0; i < Length; ++i ) {
			if( SourceWord[ i ].TypeIndex == WordNode.FRONT ) {
				continue;
			}
			int FileIndex1 = SourceWord[ i ].FileIndex + 1;
			int DefineNumber1 = DefineNumberList[ FileIndex1 ];
			string SourceText = SourceWord[ i ].Word;
			bool isDefine = false;
			for( int n = 0; n < DefineNumber1; ++n ) {
				if( SourceText == DefineList[ FileIndex1 ][ n ][ 0 ] ) {
					string[] WordDefineList = DefineList[ FileIndex1 ][ n ][ 1 ].Split( '.' );
					for( int k = 0; k < WordDefineList.Length; ++k ) {
						WordNode nNode = new WordNode( WordDefineList[ k ],
						                              SourceWord[ i ].FileIndex,
						                              SourceWord[ i ].Line,
						                              SourceWord[ i ].Column,
						                              SourceWord[ i ].Index,
						                              SourceWord[ i ].TypeIndex,
						                              SourceWord[ i ].WordLength );
						TargetWord[ newLength ] = nNode;
						++newLength;
					}
					isDefine = true;
					break;
				}
			}
			if( !isDefine ) {
				TargetWord[ newLength ] = SourceWord[ i ];
				++newLength;
			}
		}
		WordList.SetList( TargetWord, newLength );
	}
}
}




